package com.hy.demo.learn.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.nio.charset.Charset;

/**
 * <p>
 * tcp启动类
 * </p>
 *
 * @author cjl
 * @version 1.0
 * @since 2020-08-11 13:46
 */
@Component
public class StationServer implements Runnable {
    private ChannelFuture future = null;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private static final Integer PORT = 1235;
    @Resource
    private StationHandler stationHandler;

    @PostConstruct
    public void init() {
        new Thread(this).start();
    }

    public void startServer() throws Exception {
        System.out.println("Start TCP port:" + PORT);
        //boss线程监听端口，worker线程负责数据读写
        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();
        try {
            //辅助启动类
            ServerBootstrap bootstrap = new ServerBootstrap();
            //设置线程池
            bootstrap.group(bossGroup, workerGroup);
            bootstrap.childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, 2048, 65536));
            //设置socket工厂
            bootstrap.channel(NioServerSocketChannel.class);

            //设置管道工厂
            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                  //  ByteBuf delimiter = Unpooled.copiedBuffer(Constant.END.getBytes());
                    //获取管道
                    ChannelPipeline pipeline = socketChannel.pipeline();
                  //  pipeline.addLast(new DelimiterBasedFrameDecoder(2048,delimiter));
                    pipeline.addLast("decoder", new StringDecoder(Charset.forName("GBK")));
                    pipeline.addLast("encoder", new StringEncoder());
                    //处理类
                    pipeline.addLast("handler",stationHandler);
                }
            });

            //设置TCP参数
            //1.链接缓冲池的大小（ServerSocketChannel的设置）
            bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            //维持链接的活跃，清除死链接(SocketChannel的设置)
            bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            //关闭延迟发送
            bootstrap.childOption(ChannelOption.TCP_NODELAY, true);

            //绑定端口
            ChannelFuture future = bootstrap.bind(PORT).sync();

            //等待服务端监听端口关闭
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //优雅退出，释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    @Override
    public void run() {
        try {
            this.startServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @PreDestroy
    public void stop() {
        try {
            // 监听服务器关闭监听
            if (future != null)
                future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}
